//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public License
// along with this program.  If not, see http://www.gnu.org/licenses/.
// 

#include "Coordinator.h"
#include "message_k.h"
#include "message_m.h"
#include <assert.h>
#include <string.h>
#include <host_manager.h>

Define_Module(Coordinator)
;

void Coordinator::initialize()
{
	// TODO - Generated method body
	initialNumHosts = par("coordinatorNumHosts");
	numHosts = initialNumHosts;
	cntRespondedHosts = 0;
	tmpNumHosts = numHosts;
	channelPhysicalInfoRequestListTop = 0;
	// TODO - Initialize hostInfoList
}

void Coordinator::handleMessage(cMessage *msg)
{
	// TODO - Generated method body
	switch (msg->getKind())
	{
	case RequestChannelPhysicalInfoMsgKind:
	{
		cntRespondedHosts++;
		RequestChannelPhysicalInfoMsg *newRcpiMsg =
		check_and_cast<RequestChannelPhysicalInfoMsg *> (msg);
		if(newRcpiMsg->getNeedSend())
		{
			channelPhysicalInfoRequestList[channelPhysicalInfoRequestListTop++] = newRcpiMsg;
		}
		if(cntRespondedHosts == numHosts)
		{
			ChannelPhysicalInfo channelPhysicalInfoList[MAX_NUM_HOST];
			getChannelPhysicalInfo(channelPhysicalInfoRequestList, channelPhysicalInfoRequestListTop, hostInfoList, channelPhysicalInfoList);
			for(int i = 0; i < channelPhysicalInfoRequestListTop; i++)
			{
				ChannelPhysicalInfoMsg *cpiMsg = new ChannelPhysicalInfoMsg(NULL, ChannelPhysicalInfoMsgKind);
				cpiMsg->setSenderId(channelPhysicalInfoRequestList[i]->getSenderId());
				cpiMsg->setReceiverId(channelPhysicalInfoRequestList[i]->getReceiverId());
				cpiMsg->setChannelPhysicalInfo(channelPhysicalInfoList[i]);
				send(cpiMsg, "hostControlPorts$o", cpiMsg->getSenderId());
			}

			channelPhysicalInfoRequestListTop = 0;
			numHosts = tmpNumHosts;
			cntRespondedHosts = 0;
			tmpNumHosts = numHosts;
		}
	}
	break;
	case DeleteHostMsgKind:
	{
		tmpNumHosts--;
		cntRespondedHosts++;

	}
	break;
	}
}

void Coordinator::getChannelPhysicalInfo(RequestChannelPhysicalInfoMsg* requestList[], int requestListTop, HostInfo hostInfoList[], ChannelPhysicalInfo physicalInfoList[])
{
	// a basic host bit error rate count strategy
	for(int i = 0; i < requestListTop; i++)
	{
		physicalInfoList[i].dataRate = HostManager::getInstance()->getHostInfo(requestList[i]->getSenderId())->dataRate;
		physicalInfoList[i].senderId = requestList[i]->getSenderId();
		physicalInfoList[i].receiverId = requestList[i]->getReceiverId();
		physicalInfoList[i].ber = 0.01;
	}
}
